﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using Common;
using Model;
using PositionServer.Service;

namespace AcceptServer.Service
{
    class TaxiProtocol
    {
      
        OperateDataBase operateDataBase = new OperateDataBase();
        
        public byte[] TaxiRegister(byte[] realData, IPAddress clientIp)
        {
            byte[] phoneNumberbyts = new byte[6];
            Array.Copy(realData, 5, phoneNumberbyts, 0, 6);

            byte[] serialNumber = new byte[2];
            Array.Copy(realData, 11, serialNumber, 0, 2);

            string phoneNumber = OperateAgreement.GetPhoneNumInMessageHead(realData);
            //0-7  IMEI 8byte
            byte[] IMEI_bytes = new byte[8];
            Array.Copy(realData, ConstParameters.MBodySatrtIndex, IMEI_bytes, 0, 8);
            string imei = CommonRoutine.ByteToBcdString(IMEI_bytes);
            imei = imei.Remove(0, 1);

            //8-11  4byte  Version
            byte[] version_bytes = new byte[4];
            Array.Copy(realData, ConstParameters.MBodySatrtIndex + 8, version_bytes, 0, 4);
            Array.Reverse(version_bytes);
            int nowVersion = BitConverter.ToInt32(version_bytes, 0);
 

            string result = TaxiRegister(
                phoneNumber, clientIp, imei, nowVersion);
            List<byte> body = new List<byte>();
            if (result == "0" || result == "1")
            {
                int intResult = int.Parse(result);
                body.Add((byte)intResult);
            }
            else if (result.StartsWith("2|"))
            {
                body.Add(2);

                string phonestr = OperateConfig.GetCenterPhoneNumber();
                byte[] phoneBcd = CommonRoutine.BcdStringToBytes(phonestr.PadLeft(12, '0'));
                body.AddRange(phoneBcd);

                string version = AcceptMainForm.TaxiClientVersion;
                byte[] vBytes = Encoding.GetEncoding("GBK").GetBytes(version);
                //version - bytes    
                body.AddRange(vBytes);
            }

            byte[] messageHead = OperateAgreement.GetMessageHead(
                ConstParameters.CmdTaxiLoginReply, false, false,
                body.Count, phoneNumberbyts, serialNumber, 0, 0);
            byte[] tempData = OperateAgreement.PackageSendData(messageHead, body.ToArray());
            return tempData;

        }




        public void TaxiUpdataGpsInfo(byte[] realData, IPAddress clientIp)
        {
            TaxiGpsHistoryInfo taxiGpsHistoryInfo = new TaxiGpsHistoryInfo();
            byte[] tempData = new byte[5];
            Array.Copy(realData, ConstParameters.MBodySatrtIndex, tempData, 0, 5);
            taxiGpsHistoryInfo.Longitude = double.Parse(CommonRoutine.ByteToBcdString(tempData)) / 1000000;
            Array.Copy(realData, ConstParameters.MBodySatrtIndex + 5, tempData, 0, 5);
            taxiGpsHistoryInfo.Latitude = double.Parse(CommonRoutine.ByteToBcdString(tempData)) / 1000000;
            taxiGpsHistoryInfo.Taxistate = realData[ConstParameters.MBodySatrtIndex + 10];
            taxiGpsHistoryInfo.AlarmL = realData[ConstParameters.MBodySatrtIndex + 11];
            taxiGpsHistoryInfo.DriverPhoneNumber = OperateAgreement.GetPhoneNumInMessageHead(realData);
            taxiGpsHistoryInfo.Time = DateTime.Now;
            short angle = BitConverter.ToInt16(realData, ConstParameters.MBodySatrtIndex + 12);
            byte speed = realData[ConstParameters.MBodySatrtIndex + 14];
            #region

            TaxiInfo taxiInfo = new TaxiInfo
            {
                PhoneNumber = taxiGpsHistoryInfo.DriverPhoneNumber,
                UpdateTime = taxiGpsHistoryInfo.Time,             
                Latitude = taxiGpsHistoryInfo.Latitude,
                Longitude = taxiGpsHistoryInfo.Longitude,
                Ip = clientIp,           
                Angle = angle,
                Speed = speed
            };

            try
            {
                //***********
                UpdateTaxiInfo(taxiInfo);
                {
                    AcceptMainForm.DataQueue.Enqueue(taxiGpsHistoryInfo);
                }
            }
            catch (Exception ex)
            {
                CommonRoutine.HandlingExceptions(ex);
                LogService.WriteLog("TaxiProtocol.cs-111");
            }

            #endregion

        }

        private void UpdateTaxiInfo(TaxiInfo taxiInfo)
        {

            if (!AcceptMainForm.TaxiList.Contains(taxiInfo.PhoneNumber))
            {                
                TaxiRegister(taxiInfo.PhoneNumber, taxiInfo.Ip);             
            }

            TaxiInfo taxiInfoCache = AcceptMainForm.TaxiList[taxiInfo.PhoneNumber]
                as TaxiInfo;
            if (taxiInfoCache != null)
            {
                
                taxiInfoCache.PhoneNumber = taxiInfo.PhoneNumber;
                taxiInfoCache.UpdateTime = taxiInfo.UpdateTime;
                taxiInfoCache.Latitude = taxiInfo.Latitude;
                taxiInfoCache.Longitude = taxiInfo.Longitude;
 
                taxiInfoCache.Ip = taxiInfo.Ip;                
                taxiInfoCache.Angle = taxiInfo.Angle;
                taxiInfoCache.Speed = taxiInfo.Speed;
            }
        }

        
        private void TaxiRegister(string phoneNumber, IPAddress clientIp)
        {
            TaxiInfo model = operateDataBase.TaxiGetModelByPhoneNum(phoneNumber);          
            if (model!=null)
            {
                model.Ip = clientIp;
                model.UpdateTime = DateTime.Now;
                AcceptMainForm.TaxiList[phoneNumber] = model;
            }
            else
            {
                Console.WriteLine("数据库中找不到改" + phoneNumber, DateTime.Now);            
            }             
        }

        private string TaxiRegister(string phoneNumber,
          IPAddress ip, string imei, int version)
        {
            TaxiInfo model = operateDataBase.TaxiGetModelByPhoneNum(phoneNumber);          
            if (model == null)
            {
                return "0";//数据库中无此号码
            }


            if (string.IsNullOrEmpty(model.Imei))
            {
                //set IMEI 到数据库
                //更新到数据库
                if (operateDataBase.TaxiUpdateImei(phoneNumber, imei))
                {
                    Console.WriteLine("IMEI更新成功！");
                }
                else
                {
                    Console.WriteLine("IMEI更新失败！");
                }
            }
            else
            {
                if (model.Imei != imei)
                {
                    return "1";//IMEI不匹配
                }
            }
            model.Version = version.ToString();
            model.Ip = ip;
            model.UpdateTime = DateTime.Now;

            AcceptMainForm.TaxiList[phoneNumber] = model;

            return "2|" + model.Signature;
        }


        public byte[] CheckIdentity(byte[] realData, IPAddress clientIp)
        {
            byte[] phoneNumberbyts = new byte[6];
            Array.Copy(realData, 5, phoneNumberbyts, 0, 6);

            byte[] serialNumber = new byte[2];
            Array.Copy(realData, 11, serialNumber, 0, 2);

            string phoneNumber = OperateAgreement.GetPhoneNumInMessageHead(realData);
            byte[] cardidBytes = new byte[10];
            Array.Copy(realData, ConstParameters.MBodySatrtIndex,
                cardidBytes, 0, 10);

            string strId = ASCIIEncoding.GetEncoding("GBK").GetString(
                realData, ConstParameters.MBodySatrtIndex, 10).Trim('\0');
            string strPwd = ASCIIEncoding.GetEncoding("GBK").GetString(
                realData, ConstParameters.MBodySatrtIndex + 10, 10).Trim('\0');
           
            DriverInfo model = operateDataBase.DriverCheckCard(strId, strPwd);
            
            List<byte> body = new List<byte>();

            if (model==null)
            {
                body.Add(0);
            }
            else
            {
                body.Add(1);
                byte[] namebytes = new byte[10];
                byte[] tempbytes = Encoding.GetEncoding("GBK").GetBytes(model.Name);
                for (int k = 0; k < tempbytes.Length; k++)
                {
                    if (k < tempbytes.Length)
                    {
                        namebytes[k] = tempbytes[k];
                    }
                    else
                    {
                        namebytes[k] = 32;
                    }
                }
                body.AddRange(namebytes);

                //更新该车辆司机信息
                if (!AcceptMainForm.TaxiList.Contains(phoneNumber))
                {
                    TaxiRegister(phoneNumber, clientIp);
                }
                TaxiInfo taxi = AcceptMainForm.TaxiList[phoneNumber] as TaxiInfo;
                if (taxi!=null)
                {
                    taxi.Ip = clientIp;
                    taxi.DriverName = model.Name;
                    taxi.DriverCardId = model.CardId;
                    taxi.UpdateTime = DateTime.Now;
                    taxi.DriverPhoneNumber = model.PhoneNumber;
                }
                
                #region 发送给车载端

                List<OrderInfo> list = new List<OrderInfo>();
                lock (AcceptMainForm.OrderList.SyncRoot)
                { 
                    list.AddRange( AcceptMainForm.OrderList.Values.
                    Cast<OrderInfo>().Where(order=>order.CarPhoneNumber
                    == phoneNumber && order.DriverCardId == strId
                    && (order.State == OrderState.S4_OrderPaid
                    || order.State == OrderState.S5_SentInfo)).ToList());                            
                  
                }

                List<byte> msgbody = new List<byte>();
                //--------cardId  10byte
                msgbody.AddRange(cardidBytes);
                //--------orderCount  1byte
                msgbody.Add((byte)list.Count);
                if (list.Count>0)
                {
                    
                    foreach (OrderInfo order in list)
                    {
                        //--------orderId  4byte                
                        byte[] idBytes = BitConverter.GetBytes(order.Id);                        
                        Array.Reverse(idBytes);
                        msgbody.AddRange(idBytes);
                        //--------psgPhoneNumber 6byte                         
                        msgbody.AddRange(CommonRoutine.BcdStringToBytes(order.PhoneNumber.PadLeft(12, '0')));
                        //psgName 10byte 
                        byte[] psgNamebytes = new byte[10];
                        byte[] psgNameTempbytes = Encoding.GetEncoding("GBK").GetBytes(order.PassengerName);
                        for (int k = 0; k < psgNamebytes.Length; k++)
                        {
                            if (k < psgNameTempbytes.Length)
                            {
                                psgNamebytes[k] = psgNameTempbytes[k];
                            }
                            else
                            {
                                psgNamebytes[k] = 32;
                            }
                        }
                        msgbody.AddRange(psgNamebytes);
                        //--------startLng 5byte               
                        string startLngstr =
                            ((order.StartLng * Math.Pow(10, 6)).ToString().PadLeft(10, '0'));
                        byte[] lstartLngBytes = CommonRoutine.BcdStringToBytes(startLngstr);
                        msgbody.AddRange(lstartLngBytes);
                        //--------startLat 5byte               
                        string startLatstr =
                            ((order.StartLat * Math.Pow(10, 6)).ToString().PadLeft(10, '0'));
                        byte[] startLatBytes = CommonRoutine.BcdStringToBytes(startLatstr);
                        msgbody.AddRange(startLatBytes);
                        //--------endLng 5byte               
                        string endLngstr =
                            ((order.EndLng * Math.Pow(10, 6)).ToString().PadLeft(10, '0'));
                        byte[] endLngBytes = CommonRoutine.BcdStringToBytes(endLngstr);
                        msgbody.AddRange(endLngBytes);
                        //--------endLat 5byte               
                        string endLatstr =
                            ((order.EndLat * Math.Pow(10, 6)).ToString().PadLeft(10, '0'));
                        byte[] endLatBytes = CommonRoutine.BcdStringToBytes(endLatstr);
                        msgbody.AddRange(endLatBytes);
                        //--------agreeTime 7byte
                        string agreeTime = order.AgreeStartTime.ToString("yyyyMMddHHmmss");
                        byte[] agreeTimeBytes = CommonRoutine.BcdStringToBytes(agreeTime);
                        msgbody.AddRange(agreeTimeBytes);

                        //----------startAddressByteLength  1byte
                        byte[] btStartAddress = ASCIIEncoding.GetEncoding("GBK").GetBytes(
                            order.StartAddress);
                        msgbody.Add((byte)btStartAddress.Length);
                        //----------startAddrsss  startAddressByteLength byte
                        msgbody.AddRange(btStartAddress);
                        //----------endAddrsssByteLength  1byte
                        byte[] btEndAddress = ASCIIEncoding.GetEncoding("GBK").GetBytes(
                            order.EndAddress);
                        msgbody.Add((byte)btEndAddress.Length);
                        //----------endAddress   endAddrsssByteLength byte
                        msgbody.AddRange(btEndAddress);

                    }
                   
                    byte[] messageHead2 = OperateAgreement.GetMessageHead(
                        ConstParameters.CmdTaxiSendOrderInfo,
                        false, false, msgbody.Count, phoneNumberbyts,
                                                        new byte[] { 0,0}, 0, 0);
                    byte[] tempData2 = OperateAgreement.PackageSendData(messageHead2, msgbody.ToArray());

                    IPEndPoint ipEndPoint = AcceptMainForm.IpEndPointList[phoneNumber] as IPEndPoint;
                    AcceptMainForm.SendDataToIpAddress(tempData2, ipEndPoint
                        , phoneNumber);                     
                }
               
                #endregion
                 
            }           
            byte[] messageHead = OperateAgreement.GetMessageHead(
                ConstParameters.CmdTaxiCheckCardReply, false, false,
                body.Count, phoneNumberbyts, serialNumber, 0, 0);
            byte[] tempData = OperateAgreement.PackageSendData(messageHead, body.ToArray());
            return tempData;

        }

        public byte[] ChangePasswordOfIdCard(byte[] realData)
        {
            byte[] phoneNumberbyts = new byte[6];
            Array.Copy(realData, 5, phoneNumberbyts, 0, 6);

            byte[] serialNumber = new byte[2];
            Array.Copy(realData, 11, serialNumber, 0, 2);

            string phoneNumber = OperateAgreement.GetPhoneNumInMessageHead(realData);

            string strId = ASCIIEncoding.GetEncoding("GBK").GetString(
                realData, ConstParameters.MBodySatrtIndex, 10).Trim('\0');
            string strOldPwd = ASCIIEncoding.GetEncoding("GBK").GetString(
                realData, ConstParameters.MBodySatrtIndex + 10, 10).Trim('\0');

            string strNewPwd = ASCIIEncoding.GetEncoding("GBK").GetString(
              realData, ConstParameters.MBodySatrtIndex + 20, 10).Trim('\0');

            byte btResult = 0;
            bool result = operateDataBase.DriverCardChangePassword(
                strId, strOldPwd, strNewPwd);//-1 为数据库错误，0为验证失败，大于0表示通过
            if (result)
            {
                btResult = 1;
            }

            List<byte> body = new List<byte>();
            body.Add((byte)btResult);

            byte[] messageHead = OperateAgreement.GetMessageHead(
                ConstParameters.CmdTaxiChangeCardPasswordReply, false, false,
                body.Count, phoneNumberbyts, serialNumber, 0, 0);
            byte[] tempData = OperateAgreement.PackageSendData(messageHead, body.ToArray());
            return tempData;

        }


        public byte[] RequestOrderByCardId(byte[] realData)
        {
            byte[] phoneNumberbyts = new byte[6];
            Array.Copy(realData, 5, phoneNumberbyts, 0, 6);

            byte[] serialNumber = new byte[2];
            Array.Copy(realData, 11, serialNumber, 0, 2);

            string phoneNumber = OperateAgreement.GetPhoneNumInMessageHead(realData);

            byte[] cardidBytes = new byte[10];
            Array.Copy(realData, ConstParameters.MBodySatrtIndex,
                       cardidBytes, 0, 10);
            string cardId = ASCIIEncoding.GetEncoding("GBK").GetString(
                cardidBytes).Trim('\0');

            List<OrderInfo> list = new List<OrderInfo>();
            lock (AcceptMainForm.OrderList.SyncRoot)
            {
                list = AcceptMainForm.OrderList.
                   Cast<OrderInfo>().Where(order => order.CarPhoneNumber
                    == phoneNumber && order.DriverCardId == cardId
                    &&order.State != OrderState.S7_Finish
                    && order.State != OrderState.S0_Cancled)
                                     .ToList();
            }
            List<byte> msgbody = new List<byte>();
            //--------cardId  10byte
            msgbody.AddRange(cardidBytes);
            //--------orderCount  1byte
            msgbody.Add((byte) list.Count);

            foreach (OrderInfo order in list)
            {
                //--------orderId  4byte                
                msgbody.AddRange(BitConverter.GetBytes(order.Id));
                //--------driverPhoneNumber 6byte                                
                msgbody.AddRange(phoneNumberbyts);
                //--------startLng 5byte               
                string startLngstr =
                    ((order.StartLng*Math.Pow(10, 6)).ToString().PadLeft(10, '0'));
                byte[] lstartLngBytes = CommonRoutine.BcdStringToBytes(startLngstr);
                msgbody.AddRange(lstartLngBytes);
                //--------startLat 5byte               
                string startLatstr =
                    ((order.StartLng*Math.Pow(10, 6)).ToString().PadLeft(10, '0'));
                byte[] startLatBytes = CommonRoutine.BcdStringToBytes(startLatstr);
                msgbody.AddRange(startLatBytes);
                //--------endLng 5byte               
                string endLngstr =
                    ((order.StartLng*Math.Pow(10, 6)).ToString().PadLeft(10, '0'));
                byte[] endLngBytes = CommonRoutine.BcdStringToBytes(endLngstr);
                msgbody.AddRange(endLngBytes);
                //--------endLat 5byte               
                string endLatstr =
                    ((order.StartLng*Math.Pow(10, 6)).ToString().PadLeft(10, '0'));
                byte[] endLatBytes = CommonRoutine.BcdStringToBytes(endLatstr);
                msgbody.AddRange(endLatBytes);
                //--------agreeTime 8byte
                string agreeTime = order.AgreeStartTime.ToString("yyyyMMddHHmmss");
                byte[] agreeTimeBytes = CommonRoutine.BcdStringToBytes(agreeTime);
                msgbody.AddRange(agreeTimeBytes);
            }
            byte[] messageHead2 = OperateAgreement.GetMessageHead(
                ConstParameters.CmdTaxiSendOrderInfo,
                false, false, msgbody.Count, phoneNumberbyts,
                new byte[] {0, 0}, 0, 0);
            byte[] tempData = OperateAgreement.PackageSendData(messageHead2, msgbody.ToArray());

            return tempData;
        }

        public byte[] DriverAcceptOrder(byte[] realData)
        {
            byte[] phoneNumberbyts = new byte[6];
            Array.Copy(realData, 5, phoneNumberbyts, 0, 6);

            byte[] serialNumber = new byte[2];
            Array.Copy(realData, 11, serialNumber, 0, 2);

           // string phoneNumber = OperateAgreement.GetPhoneNumInMessageHead(realData);
            byte[] btOrderId = new byte[4];
            Array.Copy(realData, ConstParameters.MBodySatrtIndex,btOrderId,0 , 4);
            //int orderid = BitConverter.ToInt32(realData, ConstParameters.MBodySatrtIndex);
            Array.Reverse(btOrderId);
            int orderid = BitConverter.ToInt32(btOrderId,0);
            DateTime timeNow = DateTime.Now;
            OrderInfo order = AcceptMainForm.OrderList[orderid] as OrderInfo;
            if (order!=null)
            {
                order.State = OrderState.S6_AcceptByDriver;
                order.DriverAcceptTime = timeNow;
            }
            //记录司机接收订单的时间
            bool result = operateDataBase.OrderUpdateWhenDriverAccept(
                orderid ,timeNow.ToString("yyyy-MM-dd HH:mm:ss"));
            if (!result)
            {
                return new byte[]{0};
            }             

            List<byte> body = new List<byte>();
            body.AddRange(BitConverter.GetBytes(orderid));

            byte[] messageHead = OperateAgreement.GetMessageHead(
                ConstParameters.CmdTaxiAcceptOrderReply, false, false,
                body.Count, phoneNumberbyts, serialNumber, 0, 0);
            byte[] tempData = OperateAgreement.PackageSendData(messageHead, body.ToArray());
            return tempData;

        }


    }
}
